import * as R from 'ramda'
import _ from 'lodash'
import {
  NETWORK_OPTIONS_MAP,
  SERVER_TYPE,
  EIP_TYPES_MAP,
  EIP_CHARGE_TYPES_MAP,
  BILL_TYPES_MAP,
  SCHED_POLICY_OPTIONS_MAP,
  STORAGE_AUTO,
  SECGROUP_OPTIONS_MAP,
  FORECAST_FILTERS_MAP,
  RESOURCE_TYPES_MAP,
} from '@Compute/constants'
import { IMAGES_TYPE_MAP, HOST_CPU_ARCHS } from '@/constants/compute'
import { HYPERVISORS_MAP } from '@/constants'
import validateForm, { isRequired, isWithinRange } from '@/utils/validate'
import store from '@/store'
import i18n from '@/locales'
import { removeHttp } from '@/utils/url'
import { diskSupportTypeMedium, getOriginDiskKey } from '@/utils/common/hypervisor'

export function checkIpInSegment (i, networkData) {
  return (rule, value, cb) => {
    const isIn = isWithinRange(value, networkData.guest_ip_start, networkData.guest_ip_end)
    if (isIn) {
      cb()
    } else {
      cb(new Error(i18n.t('compute.text_205')))
    }
  }
}

export function diskValidator (rule, value, callback) {
  if (R.isNil(value) || R.isEmpty(value)) {
    return callback(new Error(i18n.t('compute.text_206')))
  }
  if (!value.startsWith('/')) {
    return callback(new Error(i18n.t('compute.text_207')))
  }
  if (value === '/') {
    return callback(new Error(i18n.t('compute.text_208')))
  }
  callback()
}

const validateValidPath = (rule, value, callback) => {
  if (value.startsWith('/')) {
    if (value === '/') {
      callback(new Error(i18n.t('compute.repo.mount_point.check_content')))
    } else {
      callback()
    }
  } else {
    callback(new Error(i18n.t('compute.repo.mount_point.check_start')))
  }
}

const validateMountNames = (rule, value, callback) => {
  if (value === undefined) {
    callback(new Error(i18n.t('common.tips.select', [i18n.t('compute.repo.storage_statement')])))
  }
  callback()
}

export const createVmDecorators = () => {
  const imageTypeInitValue = IMAGES_TYPE_MAP.standard.key

  return {
    domain: [
      'domain',
      {
        rules: [
          { validator: isRequired(), message: i18n.t('rules.domain'), trigger: 'change' },
        ],
      },
    ],
    project: [
      'project',
      {
        rules: [
          { validator: isRequired(), message: i18n.t('rules.project'), trigger: 'change' },
        ],
      },
    ],
    name: [
      'name',
      {
        initialValue: '',
        validateTrigger: 'blur',
        validateFirst: true,
        rules: [
          { required: true, message: i18n.t('compute.text_210') },
        ],
      },
    ],
    description: [
      'description',
      {
        initialValue: '',
      },
    ],
    count: [
      'count',
      {
        initialValue: 1,
        rules: [
          { required: true, message: i18n.t('compute.text_211') },
        ],
      },
    ],
    cloudregionZone: {
      cloudregion: [
        'cloudregion',
        {
          initialValue: { key: '', label: '' },
          rules: [
            { validator: isRequired(), message: i18n.t('compute.text_212') },
          ],
        },
      ],
      zone: [
        'zone',
        {
          initialValue: { key: '', label: '' },
          rules: [
            { validator: isRequired(), message: i18n.t('compute.text_213') },
          ],
        },
      ],
    },
    imageOS: {
      prefer_manager: [
        'prefer_manager',
        {
          rules: [
            { required: true, message: i18n.t('compute.text_149') },
          ],
        },
      ],
      os: [
        'os',
        {
          initialValue: '',
          rules: [
            { required: true, message: i18n.t('compute.text_153') },
          ],
        },
      ],
      image: [
        'image',
        {
          initialValue: { key: '', label: '' },
          rules: [
            { validator: isRequired(), message: i18n.t('compute.text_214') },
          ],
        },
      ],
      imageType: [
        'imageType',
        {
          initialValue: imageTypeInitValue,
        },
      ],
    },
    cloudprovider: [
      'cloudprovider',
      {
        rules: [
          { required: true, message: i18n.t('compute.text_149') },
        ],
      },
    ],
    pci: {
      pciEnable: [
        'pciEnable',
        {
          valuePropName: 'checked',
          initialValue: false,
        },
      ],
      pciDevType: i => [
        `pciDevType[${i}]`,
      ],
      pciModel: i => [
        `pciModel[${i}]`,
        {
          rules: [
            { required: true, message: i18n.t('compute.text_147') },
          ],
        },
      ],
      pciCount: i => [
        `pciCount[${i}]`,
        {
          initialValue: 1,
        },
      ],
    },
    vcpu: [
      'vcpu',
      {
        initialValue: 2,
      },
    ],
    vmem: [
      'vmem',
      {
        initialValue: 2048,
      },
    ],
    sku: [
      'sku',
      {
        rules: [
          { validator: isRequired(true, 'id'), message: i18n.t('compute.text_216') },
        ],
      },
    ],
    dataDisk: {
      type: i => [
        `dataDiskTypes[${i}]`,
        {
          rules: [
            { validator: isRequired(), message: i18n.t('compute.text_121') },
          ],
        },
      ],
      size: i => [
        `dataDiskSizes[${i}]`,
        {
          rules: [
            { required: true, message: i18n.t('compute.text_122') },
          ],
        },
      ],
      schedtag: i => [
        `dataDiskSchedtags[${i}]`,
        {
          validateTrigger: ['change', 'blur'],
          rules: [{
            required: true,
            message: i18n.t('compute.text_123'),
          }],
        },
      ],
      policy: i => [
        `dataDiskPolicys[${i}]`,
        {
          initialValue: '',
          validateTrigger: ['blur', 'change'],
          rules: [{
            required: true,
            message: i18n.t('compute.text_123'),
          }],
        },
      ],
      snapshot: i => [
        `dataDiskSnapshots[${i}]`,
        {
          validateTrigger: ['blur', 'change'],
          rules: [{
            required: true,
            message: i18n.t('compute.text_124'),
          }],
        },
      ],
      filetype: i => [
        `dataDiskFiletypes[${i}]`,
        {
          validateTrigger: ['blur', 'change'],
          rules: [{
            required: true,
            message: i18n.t('compute.text_125'),
          }],
        },
      ],
      mountPath: i => [
        `dataDiskMountPaths[${i}]`,
        {
          validateTrigger: ['blur', 'change'],
          rules: [{
            required: true,
            message: i18n.t('compute.text_126'),
          }, {
            validator: diskValidator,
          }],
        },
      ],
      storage: i => [
        `dataDiskStorages[${i}]`,
        {
          rules: [{
            required: true,
            message: i18n.t('compute.text_1351'),
          }],
        },
      ],
      iops: i => [
        `dataDiskIops[${i}]`,
        {
          rules: [{
            required: true,
            message: i18n.t('compute.iops_input_tip'),
          }],
        },
      ],
      throughput: i => [
        `dataDiskThroughputs[${i}]`,
        {
          rules: [{
            required: true,
            message: i18n.t('compute.throughput_input_tip'),
          }],
        },
      ],
      preallocation: i => [
        `dataDiskPreallocation[${i}]`,
      ],
    },
    network: {
      networkType: [
        'networkType',
        {
          initialValue: NETWORK_OPTIONS_MAP.default.key,
        },
      ],
      networkConfig: {
        vpcs: i => [
          `vpcs[${i}]`,
          {
            validateTrigger: ['change', 'blur'],
            rules: [{
              required: true,
              message: i18n.t('compute.text_194'),
            }],
          },
        ],
        networks: i => [
          `networks[${i}]`,
          {
            validateTrigger: ['change', 'blur'],
            rules: [{
              required: true,
              message: i18n.t('compute.text_217'),
            }],
          },
        ],
        ips: (i, networkData) => [
          `networkIps[${i}]`,
          {
            validateFirst: true,
            validateTrigger: ['blur', 'change'],
            rules: [
              {
                required: true,
                message: i18n.t('compute.text_218'),
              },
              {
                validator: validateForm('IPv4'),
              },
              {
                validator: checkIpInSegment(i, networkData),
              },
            ],
          },
        ],
        macs: (i, networkData) => [
          `networkMacs[${i}]`,
          {
            validateFirst: true,
            validateTrigger: ['blur', 'change'],
            rules: [
              {
                required: true,
                message: i18n.t('compute.text_806'),
              },
              {
                validator: validateForm('mac'),
              },
            ],
          },
        ],
        ipv6s: (i, networkData) => [
          `networkIPv6s[${i}]`,
          {
            validateFirst: true,
            validateTrigger: ['blur', 'change'],
          },
        ],
        devices: i => [
          `networkDevices[${i}]`,
          {
            validateTrigger: ['change', 'blur'],
            rules: [{
              required: true,
              message: i18n.t('compute.sriov_device_tips'),
            }],
          },
        ],
      },
      networkSchedtag: {
        schedtags: i => [
          `networkSchedtags[${i}]`,
          {
            validateTrigger: ['change', 'blur'],
            rules: [{
              required: true,
              message: i18n.t('compute.text_123'),
            }],
          },
        ],
        policys: (i, networkData) => [
          `networkPolicys[${i}]`,
          {
            validateTrigger: ['blur', 'change'],
            rules: [{
              required: true,
              message: i18n.t('common_256'),
            }],
          },
        ],
        devices: i => [
          `networkDevices[${i}]`,
          {
            validateTrigger: ['change', 'blur'],
            rules: [{
              required: true,
              message: i18n.t('compute.sriov_device_tips'),
            }],
          },
        ],
      },
    },
    schedPolicy: {
      schedPolicyType: [
        'schedPolicyType',
        {
          initialValue: 'default',
        },
      ],
      schedPolicyHost: [
        'schedPolicyHost',
        {
          rules: [
            { required: true, message: i18n.t('compute.text_219') },
          ],
        },
      ],
      policySchedtag: {
        schedtags: i => [
          `policySchedtagSchedtags[${i}]`,
          {
            validateTrigger: ['change', 'blur'],
            rules: [{
              required: true,
              message: i18n.t('compute.text_123'),
            }],
          },
        ],
        policys: (i, networkData) => [
          `policySchedtagPolicys[${i}]`,
          {
            validateTrigger: ['blur', 'change'],
            rules: [{
              required: true,
              message: i18n.t('common_256'),
            }],
          },
        ],
      },
    },
    duration: {
      durationStandard: [
        'durationStandard',
        {
          initialValue: 'none',
        },
      ],
      duration: [
        'duration',
        {
          initialValue: '1h',
        },
      ],
    },
    groups: {
      groupsEnable: [
        'groupsEnable',
        {
          valuePropName: 'checked',
          initialValue: false,
        },
      ],
      groups: [
        'groups',
      ],
    },
    bill: {
      billType: [
        'billType',
        {
          initialValue: 'quantity',
        },
      ],
      duration: [
        'duration',
        {
          initialValue: '1M',
        },
      ],
      autoRenew: [
        'autoRenew',
        {
          valuePropName: 'checked',
        },
      ],
    },
    resourceType: [
      'resourceType',
      {
        preserve: true,
        initialValue: RESOURCE_TYPES_MAP.shared.key,
      },
    ],
    eip: {
      type: [
        'eip_type',
        {
          initialValue: 'none',
        },
      ],
      charge_type: [
        'eip_charge_type',
      ],
      bgp_type: [
        'eip_bgp_type',
        {
          initialValue: '',
        },
      ],
      bandwidth: [
        'eip_bw',
        {
          initialValue: 30,
        },
      ],
      eip: [
        'eip',
        {
          rules: [
            { required: true, message: i18n.t('compute.text_145') },
          ],
        },
      ],
    },
    secgroup: {
      type: [
        'secgroup_type',
        {
          initialValue: 'default',
        },
      ],
      secgroup: [
        'secgroup',
        {
          validateFirst: true,
          rules: [
            { required: true, message: i18n.t('compute.text_190') },
          ],
        },
      ],
    },
    tag: [
      'tag',
      {
        rules: [
          { validator: validateForm('tagName') },
        ],
      },
    ],
    os_arch: [
      'os_arch',
      {
        rules: [
          { required: true, message: i18n.t('compute.text_1363') },
        ],
      },
    ],
    hostName: [
      'hostName',
    ],
    portMapping: {
      key: i => [
        `containerPorts[${i}]`,
        {
          rules: [
            { required: true, message: i18n.t('common.tips.input', [i18n.t('compute.repo.container_port')]) },
          ],
        },
      ],
      value: i => [
        `hostPorts[${i}]`,
      ],
    },
    containers: {
      name: i => [
        `containerNames[${i}]`,
        {
          rules: [
            { required: true, message: `${i18n.t('common.placeholder')}${i18n.t('common.name')}` },
            { validator: validateForm('k8sLabel') },
          ],
        },
      ],
      source: i => [
        `containerSources[${i}]`,
        {
          initialValue: 'custom',
        },
      ],
      registryImage: i => [
        `registryImages[${i}]`,
        {
          rules: [
            { required: true, message: i18n.t('common.tips.select', [i18n.t('compute.eci.repo.image.registry')]) },
          ],
        },
      ],
      image: i => [
        `containerimages[${i}]`,
        {
          rules: [
            { required: true, message: `${i18n.t('common.placeholder')}${i18n.t('compute.repo.container_image')}` },
          ],
        },
      ],
      cpu: i => [
        `containerCpus[${i}]`,
      ],
      memory: i => [
        `containerMemorys[${i}]`,
      ],
      command: i => [
        `containerCommands[${i}]`,
      ],
      arg: i => [
        `containerArgs[${i}]`,
      ],
      volumeMount: i => ({
        key: j => [
          `containerVolumeMountNames[${i}][${j}]`,
          {
            rules: [
              { validator: validateMountNames, trigger: 'blur' },
            ],
          },
        ],
        value: j => [
          `containerVolumeMountPaths[${i}][${j}]`,
          {
            rules: [
              { required: true, message: i18n.t('common.tips.input', []) },
              { validator: validateValidPath, trigger: 'blur' },
            ],
          },
        ],
      }),
      env: i => ({
        key: j => [
          `containerEnvNames[${i}][${j}]`,
          {
            rules: [
              { required: true, message: i18n.t('common.tips.input', [i18n.t('compute.repo.variables')]) },
            ],
          },
        ],
        value: j => [
          `containerEnvValues[${i}][${j}]`,
          {
            rules: [
              { required: true, message: i18n.t('common.tips.input', [i18n.t('compute.repo.value')]) },
            ],
          },
        ],
      }),
      privileged: i => [
        `containerPrivilegeds[${i}]`,
        {
          valuePropName: 'checked',
          initialValue: false,
        },
      ],
    },
  }
}

export class Decorator {
  decorators = {}
  // eslint-disable-next-line
  constructor(type) {
    this.type = type
  }

  createDecorators () {
    return createVmDecorators(this.type)
  }
}

/**
 * 根据表单拼装创建参数
 *
 * @export
 * @class GenCreateData
 */
export class GenCreateData {
  // eslint-disable-next-line
  constructor(fd, fi) {
    if (R.isNil(fd)) return
    this.fd = fd
    this.fi = fi
    this.createType = this.fi.createType
    this.isIDC = this.createType === SERVER_TYPE.idc
    this.isPrepaid = this.fd.resourceType === RESOURCE_TYPES_MAP.prepaid.key
  }

  /**
   * 拼装磁盘数据
   *
   * @param { Object } item       // 磁盘数据
   * @param { String } type       // 磁盘类型 sys | data
   * @param { Number } index      // 序号
   * @returns { Object }
   * @memberof GenCreateData
   */
  genDisk (item, type, index) {
    const ret = {
      disk_type: type,
      index,
      backend: item.type === STORAGE_AUTO.key ? '' : item.type,
      size: item.size * 1024,
      format: 'raw',
      fs: 'ext4',
    }
    if (type === 'sys' && this.fd.imageType === IMAGES_TYPE_MAP.iso.key && this.isWindows()) {
      ret.driver = 'ide'
    }
    if (item.medium) {
      ret.medium = item.medium
    }
    if (item.schedtags) {
      ret.schedtags = item.schedtags
    }
    if (item.filetype) {
      ret.fs = item.filetype
      if (item.filetype !== 'swap') {
        ret.mountpoint = item.mountpoint
      }
    }
    if (item.storage_id) {
      ret.storage_id = item.storage_id
    }
    if (item.iops) {
      ret.iops = item.iops
    }
    if (item.throughput) {
      ret.throughput = item.throughput
    }
    if (item.preallocation) {
      ret.preallocation = item.preallocation
    }
    // 磁盘区分介质
    if (diskSupportTypeMedium(this.fd.hypervisor)) {
      ret.backend = getOriginDiskKey(ret.backend)
    }
    return ret
  }

  isWindows () {
    let isWindows = false
    const osType = (_.get(this.fi, 'imageMsg.info.properties.os_type') || '').toLowerCase()
    const os = (_.get(this.fd, 'os') || '').toLowerCase()
    if (~[osType, os].indexOf('windows')) {
      isWindows = true
    }
    return isWindows
  }

  _getDataDiskType (dataDiskTypes) {
    if (!R.isNil(dataDiskTypes) && !R.isEmpty(dataDiskTypes)) {
      const firstKey = Object.keys(dataDiskTypes)[0]
      if (firstKey && dataDiskTypes[firstKey]) {
        return dataDiskTypes[firstKey].key
      }
    }
  }

  _genDisksArr () {
    const dataDiskType = this._getDataDiskType(this.fd.dataDiskTypes)
    const dataDisk = []

    R.forEachObjIndexed((value, key) => {
      const diskObj = {
        size: value,
        type: dataDiskType,
      }
      if (this.fd.dataDiskFiletypes && this.fd.dataDiskFiletypes[key]) {
        diskObj.filetype = this.fd.dataDiskFiletypes[key]
      }
      if (this.fd.dataDiskMountPaths && this.fd.dataDiskMountPaths[key]) {
        diskObj.mountpoint = this.fd.dataDiskMountPaths[key]
      }
      if (this.fd.dataDiskSnapshots && this.fd.dataDiskSnapshots[key]) {
        diskObj.snapshot_id = this.fd.dataDiskSnapshots[key]
      }
      if (this.fd.dataDiskSchedtags && this.fd.dataDiskSchedtags[key]) {
        diskObj.schedtags = [
          { id: this.fd.dataDiskSchedtags[key] },
        ]
        if (this.fd.dataDiskPolicys && this.fd.dataDiskPolicys[key]) {
          diskObj.schedtags[0].strategy = this.fd.dataDiskPolicys[key]
        }
      }
      if (this.fd.dataDiskStorages && this.fd.dataDiskStorages[key]) {
        // if system disk specifies storage, the data disks should do the same
        diskObj.storage_id = this.fd.dataDiskStorages[key] || this.fd.systemDiskStorage
      }
      if (this.fd.dataDiskIops && this.fd.dataDiskIops[key]) {
        diskObj.iops = this.fd.dataDiskIops[key]
      }
      if (this.fd.dataDiskThroughputs && this.fd.dataDiskThroughputs[key]) {
        diskObj.throughput = this.fd.dataDiskThroughputs[key]
      }
      if (this.fi.dataDiskMedium) {
        diskObj.medium = this.fi.dataDiskMedium
      }
      if (this.fd.dataDiskPreallocation && this.fd.dataDiskPreallocation[key]) {
        diskObj.preallocation = this.fd.dataDiskPreallocation[key]
      }
      dataDisk.push(diskObj)
    }, this.fd.dataDiskSizes)
    const disks = { data: dataDisk }
    return disks
  }

  /**
   * 组装所有磁盘数据，数据盘
   *
   * @returns { Array }
   * @memberof GenCreateData
   */
  genDisks () {
    const disks = this._genDisksArr()
    if (this.isPublic && this.isPrepaid) {
      return this.fd.spec.disks
    }
    const ret = []
    for (let i = 0, len = disks.data.length; i < len; i++) {
      ret.push(this.genDisk(disks.data[i], 'data', i + 1))
    }
    return ret
  }

  /**
   * 组装所有网络数据
   *
   * @returns { Array }
   * @memberof GenCreateData
   */
  genNetworks () {
    let ret = [{ exit: false }]
    // 指定 IP 子网
    if (this.fd.networkType === NETWORK_OPTIONS_MAP.manual.key) {
      ret = []
      R.forEachObjIndexed((value, key) => {
        const obj = {
          network: value,
        }
        if (this.fd.networkIps) {
          const address = this.fd.networkIps[key]
          if (address) {
            obj.address = address
          }
        }
        if (this.fd.networkMacs) {
          const mac = this.fd.networkMacs[key]
          if (mac) {
            obj.mac = mac
          }
        }
        if (this.fd.networkExits) {
          const exit = this.fd.networkExits[key]
          if (exit) {
            obj.exit = true
          }
        }
        if (this.fd.networkIPv6s) {
          const ipv6 = this.fd.networkIPv6s[key]
          if (ipv6) {
            obj.require_ipv6 = true
          }
        }
        if (this.fd.networkDevices) {
          const device = this.fd.networkDevices[key]
          if (device) {
            obj.sriov_device = { model: device }
          }
        }
        ret.push(obj)
      }, this.fd.networks)
    }
    // 指定 调度标签
    if (this.fd.networkType === NETWORK_OPTIONS_MAP.schedtag.key) {
      ret = []
      R.forEachObjIndexed((value, key) => {
        const obj = {
          id: value,
        }
        const strategy = this.fd.networkPolicys[key]
        if (strategy) {
          obj.strategy = strategy
        }
        if (this.fd.networkDevices) {
          const device = this.fd.networkDevices[key]
          if (device) {
            obj.sriov_device = { model: device }
          }
        }
        ret.push({
          schedtags: [obj],
        })
      }, this.fd.networkSchedtags)
    }
    return ret
  }

  /**
   * 获取配置的PCI数据
   *
   * @returns { Array }
   * @memberof GenCreateData
   */
  genPciDevices () {
    const ret = []
    const { pciCount, pciModel } = this.fd
    const pciKeys = Object.keys(this.fd.pciCount)
    pciKeys.forEach(key => {
      for (let i = 0, len = pciCount[key]; i < len; i++) {
        const regexp = /vendor=(.+):(.+)/
        const matched = pciModel[key].match(regexp)
        const model = matched[2]
        const vendor = matched[1]
        ret.push({
          model,
          vendor,
        })
      }
    })
    return ret
  }

  /**
   * 获取调度策略所提交的 key 与 value
   *
   * @returns
   * @memberof GenCreateData
   */
  getSchedPolicyValueKey () {
    const ret = {}
    // 调度策略选择为 指定宿主机
    if (this.fd.schedPolicyType === SCHED_POLICY_OPTIONS_MAP.host.key) {
      if (this.isPublic) {
        ret.key = 'prefer_manager'
      } else {
        ret.key = 'prefer_host'
      }
      ret.value = this.fd.schedPolicyHost
    } else if (this.showPreferManager()) { // 如果是通过云账号过滤镜像
      ret.key = 'prefer_manager'
      ret.value = this.fd.prefer_manager
    }

    // 调度策略选择为 调度标签
    if (this.fd.schedPolicyType === SCHED_POLICY_OPTIONS_MAP.schedtag.key) {
      ret.key = 'schedtags'
      ret.value = []
      R.forEachObjIndexed((value, key) => {
        const item = { id: value }
        if (this.fd.policySchedtagPolicys[key]) {
          item.strategy = this.fd.policySchedtagPolicys[key]
        }
        ret.value.push(item)
      }, this.fd.policySchedtagSchedtags)
    }
    return ret
  }

  /**
   * 获取平台
   *
   * @returns { String }
   * @memberof GenCreateData
   */
  getHypervisor () {
    return HYPERVISORS_MAP.pod.key
  }

  /**
   * 是否是通过云账号过滤后选择的镜像
   *
   * @returns { String }
   * @memberof GenCreateData
   */
  showPreferManager () {
    const imageMsg = IMAGES_TYPE_MAP[this.fd.imageType]
    return imageMsg && imageMsg.enable_cloudaccount
  }

  /**
   * 获取Region
   *
   * @returns { String }
   * @memberof GenCreateData
   */
  getPreferRegion () {
    if (this.isPublic && !this.isPrepaid) {
      return this.fd.sku.cloudregion_id
    }
    return this.fd.cloudregion.key
  }

  /**
   * 获取Zone
   *
   * @returns { String }
   * @memberof GenCreateData
   */
  getPreferZone () {
    let ret = ''
    if (R.is(Object, this.fd.zone)) {
      ret = this.fd.zone.key
    }
    if (R.is(String, this.fd.zone)) { // 字符串形式是公有云 AreaSelect 的 zone
      ret = this.fd.zone
    }
    return ret
  }

  /**
   * 获取CPU核数
   *
   * @returns { String }
   * @memberof GenCreateData
   */
  getCpuCount () {
    let ret = this.fd.vcpu
    if (this.isPublic && this.isPrepaid) {
      ret = this.fd.spec.vcpu_count
    }
    return ret
  }

  /**
   * 获取CPU插槽数
   * @returns
   */
  getCpuSockets () {
    return this.fi.cpuSockets
  }

  /**
   * 获取内存
   *
   * @returns { String }
   * @memberof GenCreateData
   */
  getMemSize () {
    let ret = this.fd.vmem
    if (this.isPublic && this.isPrepaid) {
      ret = this.fd.spec.vmem_size * 1024
    }
    return ret
  }

  getPreferManagerId () {
    let prefer_manager_id = ''
    const hypervisor = this.getHypervisor()
    const privateHypervisors = [HYPERVISORS_MAP.hcso.key, HYPERVISORS_MAP.hcs.key]
    if (this.isPublic || privateHypervisors.includes(hypervisor)) {
      prefer_manager_id = this.fd.cloudprovider
    }
    return prefer_manager_id
  }

  generatePod () {
    const tabKeys = this.fi.containerPanes.map(v => v.key)
    const getEnvs = (names, values) => {
      const envs = []
      if (names) {
        for (const k in names) {
          envs.push({ key: names[k], value: values[k] })
        }
      }
      return envs
    }
    const getVolumeMounts = (names, paths) => {
      const volume_mounts = []
      if (names) {
        for (const k in names) {
          volume_mounts.push({
            type: 'disk',
            disk: {
              index: names[k],
            },
            mount_path: paths[k],
          })
        }
      }
      return volume_mounts
    }
    const containers = tabKeys.map(k => {
      const pciDevices = (this.fd.pciEnable && this.genPciDevices()) || []
      const image = this.fd.registryImages?.[k] || ''

      return {
        name: this.fd.containerNames?.[k],
        image: removeHttp(image) || this.fd.containerimages?.[k],
        command: this.fd.containerCommands?.[k]?.split(' '),
        args: this.fd.containerArgs?.[k]?.split(' '),
        privileged: this.fd.containerPrivilegeds?.[k],
        devices: pciDevices.map((item, idx) => {
          return {
            type: 'isolated_device',
            isolated_device: {
              index: idx,
            },
          }
        }),
        envs: getEnvs(this.fd.containerEnvNames?.[k], this.fd.containerEnvValues?.[k]),
        volume_mounts: getVolumeMounts(this.fd.containerVolumeMountNames?.[k], this.fd.containerVolumeMountPaths?.[k]),
      }
    })
    const getPortMappings = () => {
      const port_mappings = []
      if (this.fd.containerPorts) {
        for (const k in this.fd.containerPorts) {
          port_mappings.push({
            container_port: this.fd.containerPorts[k],
            host_port: this.fd.hostPorts[k],
          })
        }
      }
      return port_mappings
    }

    return {
      containers,
      port_mappings: getPortMappings(),
    }
  }

  /**
   * 组装所有的创建数据
   *
   * @returns { Object }
   * @memberof GenCreateData
   */
  all () {
    const { create_server_auto_start = true } = store.getters.globalSetting.value || {}
    const data = {
      auto_start: create_server_auto_start,
      generate_name: this.fd.name && this.fd.name.trim(),
      description: this.fd.description,
      hypervisor: this.getHypervisor(),
      __count__: this.fd.count,
      disks: this.genDisks(),
      nets: this.genNetworks(),
      prefer_region: this.getPreferRegion(),
      vcpu_count: this.getCpuCount(),
      vmem_size: this.getMemSize(),
      project_id: (this.fd.project && this.fd.project.key) || store.getters.userInfo.projectId,
      os_arch: _.get(HOST_CPU_ARCHS, `[${this.fd.os_arch}].key`),
      hostname: this.fd.hostName,
    }
    // 非预付费资源池不会添加sku
    if (!this.isPrepaid) {
      data.sku = this.fd.sku.name
    }
    // 弹性IP
    if (this.fd.eip_type === EIP_TYPES_MAP.new.key || this.fd.eip_type === EIP_TYPES_MAP.public.key) {
      if (
        this.fd.eip_charge_type === EIP_CHARGE_TYPES_MAP.traffic.key ||
        this.fd.eip_charge_type === EIP_CHARGE_TYPES_MAP.bandwidth.key
      ) {
        if (this.fd.eip_type === EIP_TYPES_MAP.public.key) {
          data.public_ip_charge_type = this.fd.eip_charge_type
          data.public_ip_bw = this.fd.eip_bw
        } else {
          data.eip_charge_type = this.fd.eip_charge_type
          data.eip_bw = this.fd.eip_bw
        }
      }
    }
    if (this.fd.eip_type === EIP_TYPES_MAP.bind.key) {
      data.eip = this.fd.eip
    }
    // 包年包月参数
    if (this.fd.billType === BILL_TYPES_MAP.package.key) {
      data.duration = this.fd.duration
      // 自动续费
      data.auto_renew = this.fd.autoRenew
    }
    // 线路类型
    if (this.fd.eip_bgp_type) {
      data.eip_bgp_type = this.fd.eip_bgp_type
    }

    // pci
    if (this.fd.pciEnable) {
      data.isolated_devices = this.genPciDevices()
    }

    // 安全组
    if (this.fd.secgroup_type && this.fd.secgroup_type === SECGROUP_OPTIONS_MAP.bind.key) {
      data.secgroups = this.fd.secgroup
    }
    // 如果设置了调度策略则拼装调度所需数据 或者 通过云账号过滤镜像
    if ((this.fd.schedPolicyType !== SCHED_POLICY_OPTIONS_MAP.default.key) || this.showPreferManager()) {
      const schedPolicyValueKey = this.getSchedPolicyValueKey()
      data[schedPolicyValueKey.key] = schedPolicyValueKey.value
    }
    // zone
    const zoneId = this.getPreferZone()
    if (zoneId) {
      data.prefer_zone = zoneId
    }
    const prefer_manager_id = this.getPreferManagerId()
    if (prefer_manager_id) {
      data.prefer_manager_id = prefer_manager_id
    }
    // 到期释放
    if (this.fd.billType !== BILL_TYPES_MAP.package.key && this.fd.durationStandard !== 'none') {
      if (this.fd.durationStandard === 'custom') {
        data.duration = this.fd.duration
      } else {
        data.duration = this.fd.durationStandard
      }
      data.billing_type = 'postpaid'
    }
    // 镜像类型为 iso 需要加参数 cdrom
    if (this.fd.imageType === IMAGES_TYPE_MAP.iso.key || this.fd.imageType === IMAGES_TYPE_MAP.private_iso.key) {
      data.cdrom = this.fd.image.key
    }
    // 主机镜像需要guest image id参数，并且把磁盘中的镜像ID回填回去
    if (this.fd.imageType === IMAGES_TYPE_MAP.host.key) {
      data.guest_image_id = this.fd.image.key
      data.disks.forEach((val, i) => {
        if (this.fi.imageMsg.data_images && i < this.fi.imageMsg.data_images.length) {
          data.disks[i] = { ...val, image_id: this.fi.imageMsg.data_images[i].id }
        }
      })
    }
    // 主机快照需要instance_snapshot_id参数
    if (this.fd.imageType === IMAGES_TYPE_MAP.snapshot.key) {
      data.instance_snapshot_id = this.fd.image.key
      delete data.disks // 主机快照不需要 disks 字段
    } else if (this.fd.imageType === IMAGES_TYPE_MAP.backup.key) {
      data.instance_backup_id = this.fd.image.key
      // delete data.disks // 主机备份可以保留 disks 字段
    }
    // 主机组
    if (this.fd.groupsEnable && this.fd.groups && this.fd.groups.length) {
      data.groups = this.fd.groups
    }
    // 标签
    if (this.fd.tag) {
      data.__meta__ = this.fd.tag
    }
    // 插槽数
    if (this.fi.showCpuSockets) {
      data.cpu_sockets = this.getCpuSockets()
    }
    // 容器
    data.pod = this.generatePod(data)
    return data
  }

  /**
   * 获取创建预测的错误信息
   *
   * @returns { Array }
   * @memberof GenCreateData
   */
  getForecastErrors (data) {
    const errors = []
    if (data.filtered_candidates && data.filtered_candidates.length > 0) {
      for (let i = 0, len = data.filtered_candidates.length; i < len; i++) {
        const item = data.filtered_candidates[i]
        let message = `${i18n.t('dictionary.host')}【${item.name}】`
        const filterMapItem = FORECAST_FILTERS_MAP[item.filter_name]
        if (filterMapItem) {
          message += filterMapItem
        } else {
          message += i18n.t('compute.text_1325', [item.filter_name])
        }

        errors.push({
          message,
          children: item.reasons,
        })
      }
    } else {
      errors.push({
        message: i18n.t('compute.text_227'),
      })
    }
    return {
      errors,
      allow_count: data.allow_count || 0,
      req_count: data.req_count || 1,
      not_allow_reasons: data.not_allow_reasons,
    }
  }
}
